08. Anonymous Subclasses

Anonymous Subclasses

In this section, you will learn to compare lambdas and anonymous classes.

ND079 JPND C2 L01 A06 Lambdas Vs Anonymous Classes

What is an Anonymous Class?

An anonymous class is a class that is defined "in-line" and has no name, and so it is called "anonymous".

Nowadays, many anonymous classes can be replaced by lambdas, but there are still some important differences you should know about:

Anonymous Class vs. Lambda

This anonymous class…

Predicate<String> anonymousSubclass =
   new Predicate<String>() {
     @Override
     public boolean test(String s) {
       return s.trim().isEmpty();
     }
   };

… does the same thing as this lambda expresssion:

Predicate<String> lambdaInstead = s -> s.trim().isEmpty();
Anonymous Class Lambdas
Class generated at compile-time Class generated at runtime
Can override equals()/hashCode() Cannot override them; has no identity
this refers to the anonymous class this refers to the enclosing class

What's this all about?

Let's take a closer look at that last row in the table. this inside an anonymous class refers to the anonymous class, whereas this inside a lambda refers to the enclosing class. What does that mean exactly?

Consider this example:

public final class ThisExample {
  private final Runnable withLambda =
      () -> System.out.println("From lambda: " + this.getClass());
  private final Runnable withSubclass = new Runnable() {
    @Override
    public void run() {
      System.out.println("From subclass: " + this.getClass());
    }
  };

  public static void main(String[] args) {
    ThisExample thisExample = new ThisExample();
    thisExample.withLambda.run();
    thisExample.withSubclass.run();
  }
}

What do you think this program prints?

Here's what it printed on my PC:

From lambda: class com.udacitydemo.lambdas.ThisExample
From subclass: class com.udacitydemo.lambdas.ThisExample$1

Inside the lambda, this.getClass() returns the class object representing ThisExample. We'll cover class objects in more detail in the lesson on reflection, but for now the important part is that the this keyword inside the lambda references the enclosing class, which is com.udacitydemo.lambdas.ThisExample.

For the Runnable subclass, on the other hand, the program printed com.udacitydemo.lambdas.ThisExample$1. You can see that the Java compiler generated a class called com.udacitydemo.lambdas.ThisExample$1 for the anonymous lambda (yes, the class name contains a dollar sign), and the this keyword refers to that generated class! If you compile this program yourself, you'll even notice the Java compiler produces a file called ThisExample$1.class, which contains the compiled byte code for the anonymous class.

Which of these statements are true for anonymous classes?

SOLUTION:
  • The class is generated at compile-time
  • Can override the `equals()` and `hashCode()` methods

What does the following program print?

public final class Main {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println(this.getClass());
    r.run();
  }
}
SOLUTION: The program does not compile.